package com.common.client.map;

import java.util.ArrayList;

import org.gwtopenmaps.openlayers.client.Bounds;
import org.gwtopenmaps.openlayers.client.LonLat;
import org.gwtopenmaps.openlayers.client.MapOptions;
import org.gwtopenmaps.openlayers.client.layer.GMapType;
import org.gwtopenmaps.openlayers.client.layer.Google;
import org.gwtopenmaps.openlayers.client.layer.GoogleOptions;
import org.gwtopenmaps.openlayers.client.layer.Layer;
import org.gwtopenmaps.openlayers.client.layer.WMS;
import org.gwtopenmaps.openlayers.client.layer.WMSParams;
import org.gwtopenmaps.openlayers.client.util.JDoubleArray;
import org.gwtopenmaps.openlayers.client.util.JFloatArray;
import org.gwtopenmaps.openlayers.client.util.JIntArray;
import org.gwtopenmaps.openlayers.client.util.JObjectArray;
import org.gwtopenmaps.openlayers.client.util.JSObject;
import org.gwtopenmaps.openlayers.client.util.JSObjectWrapper;
import org.gwtopenmaps.openlayers.client.util.JStringArray;

import com.common.shared.map.GisLayer;
import com.common.shared.map.GisLayerOptions;
import com.common.shared.map.GisMap;
import com.common.shared.map.GisMapProperties;
import com.common.shared.map.MLParameter;

public class MapHelper {
	public static final int STRING_PARAMETER = 1;
	public static final int INT_PARAMETER = 2;
	public static final int FLOAT_PARAMETER = 3;
	public static final int DOUBLE_PARAMETER = 4;
	public static final int BOOLEAN_PARAMETER = 5;
	public static final int STRING_ARR_PARAMETER = 6;
	public static final int INT_ARR_PARAMETER = 7;
	public static final int FLOAT_ARR_PARAMETER = 8;
	public static final int DOUBLE_ARR_PARAMETER = 9;
	public static final int BOOLEAN_ARR_PARAMETER = 10;
	public static final int LONLAN_PARAMETER = 11;
	public static final int BOUNDS_PARAMETER = 12;

	public static final int G_SATELLITE_MAP = 1;
	public static final int G_NORMAL_MAP = 2;
	public static final int G_HYBRID_MAP = 3;

	public static MapOptions createMapOptions(GisMap gisMap) {
		MapOptions mapOptions = new MapOptions();
		mapOptions.setControls(new JObjectArray(new JSObject[] {}));
		ArrayList<GisMapProperties> gisMapProperties = gisMap
				.getGisMaProperties();
		for (GisMapProperties mapProperties : gisMapProperties) {
			setProperty(mapOptions.getJSObject(), mapProperties);
			String propName = mapProperties.getPropertie_name();
			String prop = STRING_ARR_PARAMETER < mapProperties.getPtype() ? mapOptions
					.getJSObject().getProperty(propName).toString()
					: mapOptions.getJSObject().getPropertyAsString(propName);
			System.out.println(propName + " :  " + prop);
		}
		return mapOptions;
	}

	public static Layer[] createLayers(GisMap gisMap, Layer[] additional,
			Boolean without_showinmap) {
		ArrayList<GisLayer> gisLayers = gisMap.getGisLayers();
		int mainsize = gisLayers.size();
		ArrayList<Layer> layers = new ArrayList<Layer>();

		for (int i = 0; i < mainsize; i++) {

			GisLayer l = gisLayers.get(i);
			if (without_showinmap != null) {
				if (l.isShowinmap() != without_showinmap.booleanValue())
					continue;
			} else if (!l.isShowinmap())
				continue;
			Layer layer = createLayer(l);

			layers.add(layer);
		}
		for (int i = 0; i < additional.length; i++) {
			layers.add(additional[i]);

		}
		return layers.toArray(new Layer[] {});
	}

	public static Layer createLayer(GisLayer l) {
		Layer layer = null;

		if (l.isIswms()) {
			WMSParams wmsParams = new WMSParams();
			ArrayList<GisLayerOptions> gisLayerOptions = l.getGisLayerOptions();
			for (GisLayerOptions layerOptions : gisLayerOptions) {
				setProperty(wmsParams.getJSObject(), layerOptions);
			}
			layer = new WMS(l.getLayername(), l.getWmsurl(), wmsParams);
			layer.setIsBaseLayer(l.isBaselayer());
			layer.getJSObject().setProperty("_GisLayerID", l.getId());
		} else {
			GoogleOptions go = new GoogleOptions();
			switch (l.getGmaptype()) {
			case G_SATELLITE_MAP:
				go.setType(GMapType.G_SATELLITE_MAP);
				break;
			case G_NORMAL_MAP:
				go.setType(GMapType.G_NORMAL_MAP);
				break;
			case G_HYBRID_MAP:
				go.setType(GMapType.G_HYBRID_MAP);
				break;
			default:
				break;
			}
			go.setSphericalMercator(l.isSphericalmercator());
			ArrayList<GisLayerOptions> gisLayerOptions = l.getGisLayerOptions();
			for (GisLayerOptions layerOptions : gisLayerOptions) {
				setProperty(go.getJSObject(), layerOptions);
			}
			layer = new Google(l.getTitle(), go);
		}
		layer.setIsBaseLayer(l.isBaselayer());
		return layer;
	}

	private static void setProperty(JSObject jsObject, MLParameter mlParameter) {
		switch (mlParameter.getPtype()) {
		case STRING_PARAMETER:
			jsObject.setProperty(mlParameter.getPropertie_name(),
					mlParameter.getPropertie_value());
			break;
		case INT_PARAMETER:
			jsObject.setProperty(mlParameter.getPropertie_name(),
					Integer.parseInt(mlParameter.getPropertie_value()));
			break;
		case FLOAT_PARAMETER:
			jsObject.setProperty(mlParameter.getPropertie_name(),
					Float.parseFloat(mlParameter.getPropertie_value()));
			break;
		case DOUBLE_PARAMETER:
			jsObject.setProperty(mlParameter.getPropertie_name(),
					Double.parseDouble(mlParameter.getPropertie_value()));
			break;
		case BOOLEAN_PARAMETER:
			jsObject.setProperty(mlParameter.getPropertie_name(), mlParameter
					.getPropertie_value().equals("true") ? true : false);
			break;
		case STRING_ARR_PARAMETER:
		case INT_ARR_PARAMETER:
		case FLOAT_ARR_PARAMETER:
		case DOUBLE_ARR_PARAMETER:
		case LONLAN_PARAMETER:
		case BOUNDS_PARAMETER:
			JSObjectWrapper obj = getWraper(mlParameter.getPropertie_value(),
					mlParameter.getPtype());
			if (obj != null) {
				jsObject.setProperty(mlParameter.getPropertie_name(),
						obj.getJSObject());
			} else {
				jsObject.setProperty(mlParameter.getPropertie_name(),
						mlParameter.getPropertie_value());
			}
			break;

		default:
			jsObject.setProperty(mlParameter.getPropertie_name(),
					mlParameter.getPropertie_value());
		}
	}

	public static JSObjectWrapper getWraper(String value, int type) {
		switch (type) {
		case STRING_ARR_PARAMETER:
			JStringArray stringArray = new JStringArray(value.split(","));
			return stringArray;
		case INT_ARR_PARAMETER:
			String[] intStrings = value.split(",");
			int[] integers = new int[intStrings.length];
			for (int i = 0; i < integers.length; i++) {
				integers[i] = Integer.parseInt(intStrings[i].trim());
			}
			JIntArray intArray = new JIntArray(integers);

			return intArray;
		case FLOAT_ARR_PARAMETER:
			String[] floatStrings = value.split(",");
			float[] floats = new float[floatStrings.length];
			for (int i = 0; i < floats.length; i++) {
				floats[i] = Float.parseFloat(floatStrings[i].trim());
			}
			JFloatArray floatArray = JFloatArray.create(floats);

			return floatArray;
		case DOUBLE_ARR_PARAMETER:
			String[] doubleStrings = value.split(",");
			double[] doubles = new double[doubleStrings.length];
			for (int i = 0; i < doubles.length; i++) {
				doubles[i] = Double.parseDouble(doubleStrings[i].trim());
			}
			JDoubleArray doubleArray = JDoubleArray.create(doubles);

			return doubleArray;
		case LONLAN_PARAMETER:
			String[] lonLatStrings = value.split(",");
			LonLat lonLat = new LonLat(Double.parseDouble(lonLatStrings[0]
					.trim()), Double.parseDouble(lonLatStrings[1].trim()));

			return lonLat;
		case BOUNDS_PARAMETER:
			String[] boundsStrings = value.split(",");
			Bounds bounds = new Bounds(Double.parseDouble(boundsStrings[0]
					.trim()), Double.parseDouble(boundsStrings[1].trim()),
					Double.parseDouble(boundsStrings[2].trim()),
					Double.parseDouble(boundsStrings[3].trim()));

			return bounds;

		default:
			return null;
		}
	}

}
